package com.nio.socket;

import org.omg.CORBA.WrongTransaction;

import javax.swing.event.ChangeEvent;
import java.awt.event.ItemEvent;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by fangjicai on 2020/6/3.
 */
public class NioSocketServer {

    //通道管理器 Selector
    private static Selector selector;

    public static void main(String[] args) throws IOException {
        //创建通道管理器 selector
        selector = Selector.open();
        //创建通道serversocketchannel
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        //// 将ServerSocketChannel对应的ServerSocket绑定到指定端口(port)
        ServerSocket serverSocket = serverSocketChannel.socket();
        serverSocket.bind(new InetSocketAddress(8989));

        /**
         * 将通道(Channel)注册到通道管理器(Selector)，并为该通道注册selectionKey.OP_ACCEPT事件
         * 注册该事件后，当事件到达的时候，selector.select()会返回，
         * 如果事件没有到达selector.select()会一直阻塞。
         */
        serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
        //循环处理
        while(true){
            //当注册事件到达时，方法返回，否则该方法会一直阻塞
            selector.select();
            //获取监听事件
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while(iterator.hasNext()){
                //获取时间
                SelectionKey key = iterator.next();
                //客户端请求连接事件，接受客户端连接就绪
                if(key.isAcceptable()){
                    acceptHandler(key);
                } else if(key.isReadable()){//监听读事件，对读事件进行处理
                    readHandler(key);
                }
                //移除时间，避免重复处理
                iterator.remove();
            }
        }



    }

    /**
     * 处理客户端连接成功事件
     * @param key
     * @throws IOException
     */
    private static void acceptHandler(SelectionKey key) throws  IOException{
        //获取客户端连接通道
        ServerSocketChannel server=(ServerSocketChannel)key.channel();
        SocketChannel socketChannel = server.accept();
        //设置非阻塞
        socketChannel.configureBlocking(false);
        //信息通过通道发送给客户端
        socketChannel.write(ByteBuffer.wrap(new String("hello client ,扑街！").getBytes()));
        //给通道设置读事件，客户端监听到读事件后，进行读取操作
        socketChannel.register(selector,SelectionKey.OP_READ);
    }

    private static void readHandler(SelectionKey key) throws IOException{
        SocketChannel channel=(SocketChannel)key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int count;
        buffer.clear();
        while ((count=channel.read(buffer))>0){
            //把buffer的当前位置更改为buffer缓冲区的第一个位置
            buffer.flip();
           byte[] bytes= new byte[buffer.remaining()];
           buffer.get(bytes);
            System.out.println("读取客户端消息："+new String(bytes));
        }
        if(count<0){
            channel.close();
        }
    }




}
